package com.generator.service.impl;

import com.generator.dao.mybatis.mapper.MetaDataMapper;
import com.generator.domain.Column;
import com.generator.domain.Table;
import com.generator.service.MybatisGeneratorService;
import com.generator.service.common.Constants;
import com.generator.service.common.FieldUtil;
import com.generator.service.common.TableUtil;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;

import javax.annotation.Resource;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created with IntelliJ IDEA.
 * User: wangyanginfo
 * Date: 12-9-21
 * Time: 下午1:28
 * To change this template use File | Settings | File Templates.
 */
@Service("mybatisGeneratorService")
public class MybatisGeneratorServiceImpl implements MybatisGeneratorService {

    @Resource
    private MetaDataMapper metaDataMapper;

    private final static String[] types = new String[]{"TABLE", "VIEW"};

    private final static String ftlDir = "ftl";

    private final static String CharacterSet = "UTF-8";


    /**
     * 生成Mapper文件
     *
     * @param params 生成文件目录
     * @return
     */
    @Override
    public boolean generateMapper(Map<String, Object> params) {
        try {
            String databaseName = (String) params.get(Constants.DATABASE_NAME);
            String tablePrefix = (String) params.get(Constants.TABLE_PREFIX);
            String tableSuffix = (String) params.get(Constants.TABLE_SUFFIX);
            boolean isCase = (Boolean) params.get(Constants.IS_CASE);
            String targetPath = (String) params.get(Constants.TARGET_PATH);
            String FileSuffix = (String) params.get(Constants.FILE_SUFFIX);

            List<Table> tables = getDatabaseMetaData(databaseName, tablePrefix, tableSuffix, isCase);

            params.put(Constants.MAPPER_PACKAGENAME, "com.generator.dao.mybatis.mapper");
            params.put(Constants.MODEL_PACKAGENAME, "com.generator.dao.mybatis.model");
            params.put(Constants.USER_NAME, "wangyang");
            params.put(Constants.DATA_TIME, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));

            /* 在整个应用的生命周期中，这个工作你应该只做一次。 */
            /* 创建和调整配置。 */
            Configuration cfg = new Configuration();
            cfg.setDirectoryForTemplateLoading(getTemplateDir());
            // 编码设置1
            cfg.setDefaultEncoding(CharacterSet);
            cfg.setObjectWrapper(new DefaultObjectWrapper());
            /* 在整个应用的生命周期中，这个工作你可以执行多次 */
            /* 获取或创建模板*/
            Template temp = cfg.getTemplate("mapper.ftl");
            // 编码设置2
            temp.setEncoding(CharacterSet);

            for (Table table : tables) {
                File file = new File(targetPath + table.getClassName() + FileSuffix);
                Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), CharacterSet));
                /* 将模板和数据模型合并 */
                temp.process(params, out);
            }
            //out.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 生成MapperXml文件
     *
     * @param params 生成文件目录
     * @return
     */
    @Override
    public boolean generateMapperXml(Map<String, Object> params) {
        return false;
    }

    /**
     * 生成Model文件
     *
     * @param params 生成文件目录
     * @return
     */
    @Override
    public boolean generateModel(Map<String, Object> params) {
        return false;
    }

    /**
     * 生成Dao接口文件
     *
     * @param params 生成文件目录
     * @return
     */
    @Override
    public boolean generateDao(Map<String, Object> params) {
        return false;
    }

    /**
     * 生成Dao实现文件
     *
     * @param params 生成文件目录
     * @return
     */
    @Override
    public boolean generateDaoImpl(Map<String, Object> params) {
        return false;
    }

    /**
     * 生成Mybatis配置文件
     *
     * @param params 生成文件目录
     * @return
     */
    @Override
    public boolean generateMybatisConfig(Map<String, Object> params) {
        return false;
    }

    private List<Table> getDatabaseMetaData(String database, String prefix, String suffix, boolean isCase) {

        List<Table> tables = null;//metaDataMapper.queryTable(database);

        Map<String, String> params = new HashMap<String, String>();
        params.put("database", database);
        for (Table table : tables) {
            table.setClassName(TableUtil.getClassName(table.getName(), prefix, suffix, isCase));
            params.put("tableName", table.getName());
            List<Column> columns = null;//metaDataMapper.queryColumn(params);
            for (Column column : columns) {
                if (column.getKey() != null && column.getKey().equals(Column.PRI)) {
                    table.getIds().add(column);
                }
                column.setFieldType(FieldUtil.getFieldTypeByMsql(column.getTypeName()));
                column.setFieldName(FieldUtil.getFieldName(column.getName(), true));
            }
            table.setColumns(columns);
        }
        return tables;
    }

    private List<Table> getDatabaseMetaData(String database) {
        // 查询数据库中的表
        List<Table> tables = metaDataMapper.queryTable(database);
        // 列查询参数Map
        Map<String, String> params = new HashMap<String, String>();
        params.put("database", database);
        for (Table table : tables) {
            params.put("tableName", table.getName());
            List<Column> columns = metaDataMapper.queryColumn(params);
            table.setColumns(columns);
        }
        return tables;
    }

    /**
     * 获取模板文件所在目录
     *
     * @return
     * @throws Exception
     */
    private File getTemplateDir() throws Exception {
        return ResourceUtils.getFile(ResourceUtils.CLASSPATH_URL_PREFIX + ftlDir);
    }
}
